#include "../include/mapLoader.hpp"
#include "../include/Tileset/tileset.hpp"
#include "../include/Tileset/tilesetImage.hpp"
#include "../include/Tileset/tilesetImageLayer.hpp"
#include "../include/Tileset/tilesetLayer.hpp"
#include "../include/Tileset/tilesetObjectGroup.hpp"
#include <tinyxml.h>
#include <string>
#include <iostream>
#include <stdio.h>

Tmx::Map::~Map()
{
	std::vector<Tileset *>::iterator tsIter;
	for (tsIter = tilesets.begin(); tsIter != tilesets.end(); tsIter++) {
		Tileset *ts = *tsIter;
		delete ts;
	}
	std::vector<Layer *>::iterator layerIter;
	for (layerIter = layers.begin(); layerIter != layers.end(); layerIter++) {
		Layer *lyr = *layerIter;
		delete lyr;
	}
	std::vector<ObjectGroup *>::iterator objGrpIter;
	for (objGrpIter = objectGroups.begin(); objGrpIter != objectGroups.end(); objGrpIter++) {
		ObjectGroup *objGrp = *objGrpIter;
		delete objGrp;
	}
	std::vector<ImageLayer *>::iterator ilIter;
	for (ilIter = imageLayers.begin(); ilIter != imageLayers.end(); ilIter++) {
		ImageLayer *il = *ilIter;
		delete il;
	}
}

void Tmx::Map::parse()
{
  // read XML document into file.
  char *text;
  int fileSize;
  int depth = 0;
  FILE *file = fopen(fileName.c_str(), "rb");
  if (!file) {
	  Error = true;
	  std::cout << "Error opening " << fileName << "\n";
	  return;
  }
  fseek(file, 0, SEEK_END);
  fileSize = ftell(file);
  fseek(file, 0, SEEK_SET);
  if (fileSize <= 0) {
	  Error = true;
	  std::cout << "Invalid file: " << fileName << "\n";
	  return;
  }
  text = new char[fileSize+1];
  fread(text, 1, fileSize, file);
  fclose(file);

  TiXmlDocument doc;
  doc.Parse(text);
  if (doc.Error()) {
	  Error = true;
	  std::cout << "Error interpreting XML\n";
  }
  TiXmlNode *mapNode = doc.FirstChild("map");
  TiXmlElement* mapElement = mapNode->ToElement();
  mapElement->Attribute("width", &mapWidth);
  mapElement->Attribute("height", &mapHeight);
  mapElement->Attribute("tilewidth", &tileWidth);
  mapElement->Attribute("tileheight", &tileHeight);
  std::string orientationStr = mapElement->Attribute("orientation");
  if (!orientationStr.compare("orthogonal"))
  {
	  orientation = TMX_MO_ORTHOGONAL;
  }
  else if (!orientationStr.compare("isometric"))
  {
	  orientation = TMX_MO_ISOMETRIC;
  }
  else if (!orientationStr.compare("staggered"))
  {
	  orientation = TMX_MO_STAGGERED;
  }
  TiXmlNode *node = mapElement->FirstChild();
  while (node) {
    // TODO properties not yet implemented
	// if (strcmp(node->Value(), "properties") == 0) {
	//   properties.parse(node);
	// }
	if (strcmp(node->Value(), "tileset") == 0) {
	  Tileset *tileset = new Tileset();
	  tileset->parse(node->ToElement());
	  tilesets.push_back(tileset);
	}
	if (strcmp(node->Value(), "layer") == 0) {
	  Layer *layer = new Layer(this, depth);
	  layer->parse(node->ToElement());
	  layers.push_back(layer);
	  depth++;
	}
	if (strcmp(node->Value(), "objectgroup") == 0) {
	  ObjectGroup *objectGroup = new ObjectGroup(depth);
	  objectGroup->parse(node->ToElement());
	  objectGroups.push_back(objectGroup);
	  depth++;
	}
	if (strcmp(node->Value(), "imagelayer") == 0) {
	  ImageLayer *imageLayer = new ImageLayer(this, depth);
	  imageLayer->parse(node->ToElement());
	  imageLayers.push_back(imageLayer);
	}
	node = node->NextSibling();
  }
  delete[] text;
} //

int Tmx::Map::FindTilesetIndex(int gid)
{
  for (int i = tilesets.size() - 1; i > -1; --i) {
    if (gid >= tilesets[i]->getFirstGid())
	  return i;
	}
	return -1;
}

Tmx::Tileset *Tmx::Map::FindTileset(int gid)
{
  for (int i=tilesets.size() - 1; i > -1; --i)
  {
    if (gid >= tilesets[i]->getFirstGid()) {
	  return tilesets[i];
	}
  }
  return NULL;
}
